// 官方题解，待理解
#include <iostream>
using std::cin;
using std::cout;
using std::max;
using std::min;
#include <vector>
using std::vector;

typedef long long int ll;

ll n, q;      // n: 区间数量, q: 查询数量
vector<ll> w; // 存储每个区间的宽度

// 定义块结构，用于管理具有相同性质的区间组
typedef struct {
  ll li;      // 区间组的最小索引
  ll ri;      // 区间组的最大索引
  ll gravity; // 重力方向：-1表示左端点固定，+1表示右端点固定
  ll x;       // 固定端点的坐标值
} Block;
vector<Block> bar; // 存储所有区间组的列表

// 处理查询1和2的核心函数
// v: 要处理的区间索引, dir: 方向（-1表示左端点，+1表示右端点）
void barclear(ll v, ll dir) {
  while (true) {
    Block b = bar.back(); // 获取最后一个块
    bar.pop_back();       // 移除最后一个块

    if (b.ri >= v) { // 如果当前块包含目标区间v
      // 如果v不是块的最后一个区间，将剩余区间重新加入列表
      if (v + 1 <= b.ri) {
        bar.push_back({v + 1, b.ri, b.gravity, b.x});
      }

      // 计算区间v的左右端点坐标
      ll fl, fr;
      if (b.gravity < 0) { // 左端点固定模式
        fl = b.x;          // 左端点坐标
        fr = fl + w[v];    // 右端点坐标 = 左端点 + 宽度
      } else {             // 右端点固定模式
        fr = b.x;          // 右端点坐标
        fl = fr - w[v];    // 左端点坐标 = 右端点 - 宽度
      }

      // 根据方向选择固定点坐标
      ll currx = ((dir < 0) ? fl : fr);
      // 将新区间组[0, v]加入列表
      bar.push_back({0, v, dir, currx});
      break;
    }
  }
}

int main(void) {
  cin >> n;
  w.resize(n);
  for (ll i = 0; i < n; i++) {
    cin >> w[i]; // 读取每个区间的宽度
  }

  // 初始化：将所有区间作为一个组，左端点固定在0
  bar.push_back({0, n - 1, -1, 0});

  cin >> q;
  for (ll qi = 0; qi < q; qi++) {
    ll type;
    cin >> type;
    if (type == 1) {
      ll v;
      cin >> v;
      --v; // 转换为0-based索引
      // 查询类型1：处理区间v的左端点
      barclear(v, -1);
    } else if (type == 2) {
      ll v;
      cin >> v;
      --v; // 转换为0-based索引
      // 查询类型2：处理区间v的右端点
      barclear(v, +1);
    } else if (type == 3) {
      ll x;
      cin >> x;
      // 查询类型3：查询包含坐标x的区间数量
      ll ans;
      ll idx;

      {
        // 第一步：在区间组列表中进行二分查找
        // 找到包含坐标x的区间组
        ll ok = -1, ng = bar.size();
        while (ok + 1 < ng) {
          ll med = (ok + ng) / 2;
          ll fl, fr;

          // 计算当前区间组中最大区间的端点坐标
          if (bar[med].gravity < 0) {
            fl = bar[med].x;          // 左端点固定
            fr = fl + w[bar[med].ri]; // 右端点 = 左端点 + 最大宽度
          } else {
            fr = bar[med].x;          // 右端点固定
            fl = fr - w[bar[med].ri]; // 左端点 = 右端点 - 最大宽度
          }

          // 检查坐标x是否在当前区间组的最大区间内
          if (fl <= x && x < fr) {
            ok = med; // 包含x，继续向右搜索
          } else {
            ng = med; // 不包含x，向左搜索
          }
        }
        idx = ok; // 找到包含x的区间组索引
      }

      if (idx < 0) {
        // 没有区间包含坐标x
        ans = 0;
      } else {
        // 第二步：在找到的区间组内进行二分查找
        // 找到第一个包含坐标x的区间
        ll fl, fr;
        ll ok = bar[idx].ri, ng = bar[idx].li - 1;
        while (ng + 1 < ok) {
          ll med = (ok + ng) / 2;

          // 计算当前区间med的端点坐标
          if (bar[idx].gravity < 0) {
            fl = bar[idx].x;  // 左端点固定
            fr = fl + w[med]; // 右端点 = 左端点 + 当前区间宽度
          } else {
            fr = bar[idx].x;  // 右端点固定
            fl = fr - w[med]; // 左端点 = 右端点 - 当前区间宽度
          }

          // 检查坐标x是否在当前区间内
          if (fl <= x && x < fr) {
            ok = med; // 包含x，继续向左搜索更小的区间
          } else {
            ng = med; // 不包含x，向右搜索更大的区间
          }
        }
        // 计算包含x的区间数量：从区间ok到最后一个区间
        ans = n - ok;
      }

      cout << ans << "\n";
    }
  }

  return 0;
}